package com.hibase.common.util;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Properties;

import com.alibaba.fastjson.util.IOUtils;
import com.hibase.common.exception.HibaseException;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import lombok.extern.log4j.Log4j2;

@Log4j2
public class SFTPUtils {

	private static Session sshSession;

	/**
	 * 连接sftp服务器
	 * 
	 * @param host     ftp地址
	 * @param port     端口
	 * @param userName 账号
	 * @param password 密码
	 * @return
	 */
	public static ChannelSftp sftpConnection(String host, int port, String userName, String password) {
		JSch jsch = new JSch();
		ChannelSftp channelSftp;
		try {
			jsch.getSession(userName, host, port);
			sshSession = jsch.getSession(userName, host, port);
			sshSession.setPassword(password);
			Properties properties = new Properties();
			properties.put("StrictHostKeyChecking", "no");
			sshSession.setConfig(properties);
			sshSession.connect();
			Channel channel = sshSession.openChannel("sftp");
			channel.connect();
			channelSftp = (ChannelSftp) channel;
		} catch (JSchException e) {
			e.printStackTrace();
			throw new HibaseException("Sftp服务器登录异常!");
		}
		return channelSftp;
	}

	/**
	 * @description 退出Sftp服务器登录
	 * @return
	 **/
	public static void sftpClose(ChannelSftp channelSftp) {
		if (channelSftp != null) {
			if (channelSftp.isConnected()) {
				channelSftp.disconnect();
			}
		}
	}

	/**
	 * 关闭session
	 */
	public static void sessionClose() {
		if (sshSession != null) {
			if (sshSession.isConnected()) {
				sshSession.disconnect();
				sshSession = null;
			}
		}
	}

	/**
	 * 下载sftp文件
	 * 
	 * @param sftp
	 * @param newFileName 新文件名称
	 * @param path        文件路径
	 * @param fileName    文件名称
	 * @param downUrl     下载到本地的路径
	 * @throws Exception
	 */
	public static void downSftpFile(ChannelSftp sftp, String newFileName, String path, String fileName, String downUrl)
			throws Exception {

		OutputStream os = null;
		try {
			File localFile = new File(downUrl + File.separator + newFileName);
			if (!localFile.getParentFile().exists()) {
				localFile.getParentFile().mkdirs();
				localFile.createNewFile();
			}

			if (path != null && !"".equals(path)) {
				sftp.cd(path);// 进入所在路径
			}
			os = new FileOutputStream(localFile);
			sftp.get(path + fileName, os);
			os.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @Title: SFTPUtils
	 * @Description: 读取outputStream流
	 * @author TimBrian
	 * @since 2021年10月22日 上午11:17:03
	 * @param sftp
	 * @param path     需要读取的文件路径
	 * @param fileName 需要读取的文件名称
	 * @return
	 * @throws Exception
	 */
	public static ByteArrayOutputStream downSftpSO(ChannelSftp sftp, String path, String fileName) throws Exception {

		ByteArrayOutputStream os = new ByteArrayOutputStream();
		if (path != null && !"".equals(path)) {
			sftp.cd(path);// 进入所在路径
		}
		try (InputStream is = sftp.get(path + fileName)) {
			byte bytes[] = new byte[1024];
			int lenthg = 0;
			while ((lenthg = is.read(bytes)) != -1) {
				os.write(bytes, 0, lenthg);
			}
			os.flush();
			return os;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (os != null) {
				os.close();
			}
		}
		return os;
	}

	/**
	 * 将输入流的数据上传到sftp作为文件
	 *
	 * @param directory    上传到该目录
	 * @param sftpFileName sftp端文件名
	 * @param in           输入流
	 * @throws SftpException
	 * @throws Exception
	 */
	public static void upload(String directory, String sftpFileName, InputStream input, ChannelSftp sftp)
			throws SftpException {
		try {
			sftp.cd(directory);
		} catch (SftpException e) {
			log.warn("directory is not exist");
			sftp.mkdir(directory);
			sftp.cd(directory);
		}
		sftp.put(input, sftpFileName);
		log.info("file:{} is upload successful", sftpFileName);
	}

	/**
	 * 上传单个文件
	 *
	 * @param directory  上传到sftp目录
	 * @param uploadFile 要上传的文件,包括路径
	 * @throws FileNotFoundException
	 * @throws SftpException
	 * @throws Exception
	 */
	public static void upload(String directory, String uploadFile, ChannelSftp sftp)
			throws FileNotFoundException, SftpException {
		File file = new File(uploadFile);
		upload(directory, file.getName(), new FileInputStream(file), sftp);
	}

	/**
	 * 将byte[]上传到sftp，作为文件。注意:从String生成byte[]是，要指定字符集。
	 *
	 * @param directory    上传到sftp目录
	 * @param sftpFileName 文件在sftp端的命名
	 * @param byteArr      要上传的字节数组
	 * @throws SftpException
	 * @throws Exception
	 */
	public static void upload(String directory, String sftpFileName, byte[] byteArr, ChannelSftp sftp)
			throws SftpException {
		upload(directory, sftpFileName, new ByteArrayInputStream(byteArr), sftp);
	}

	/**
	 * 将字符串按照指定的字符编码上传到sftp
	 *
	 * @param directory    上传到sftp目录
	 * @param sftpFileName 文件在sftp端的命名
	 * @param dataStr      待上传的数据
	 * @param charsetName  sftp上的文件，按该字符编码保存
	 * @throws UnsupportedEncodingException
	 * @throws SftpException
	 * @throws Exception
	 */
	public static void upload(String directory, String sftpFileName, String dataStr, String charsetName,
			ChannelSftp sftp) throws UnsupportedEncodingException, SftpException {
		upload(directory, sftpFileName, new ByteArrayInputStream(dataStr.getBytes(charsetName)), sftp);
	}

	/**
	 * 下载文件
	 *
	 * @param directory    下载目录
	 * @param downloadFile 下载的文件
	 * @param saveFile     存在本地的路径
	 * @throws SftpException
	 * @throws FileNotFoundException
	 * @throws Exception
	 */
	public static void download(String directory, String downloadFile, String saveFile, ChannelSftp sftp)
			throws SftpException, FileNotFoundException {
		if (directory != null && !"".equals(directory)) {
			sftp.cd(directory);
		}
		File file = new File(saveFile);
		sftp.get(downloadFile, new FileOutputStream(file));
		log.info("file:{} is download successful", downloadFile);
	}

	/**
	 * 删除文件
	 *
	 * @param directory  要删除文件所在目录
	 * @param deleteFile 要删除的文件
	 * @throws SftpException
	 * @throws Exception
	 */
	public static void delete(String directory, String deleteFile, ChannelSftp sftp) throws SftpException {
		sftp.cd(directory);
		sftp.rm(deleteFile);
	}

	public static void main(String[] args) throws Exception {
		// 1 从远程目录中下载文件
		String today = DateUtils.today();

		// 远程目录
		String remoteDirectory = File.separator + "VMIFTP_HK" + File.separator + "HC" + File.separator + "from_lenovo";
		remoteDirectory = "/VMIFTP_HK/HC/from_lenovo/";
		// 需要下载的文件名
		String downloadFile = "test.txt";
		// 本地存放的目录
		String locationDirectory = "D:\\ftp" + "\\" + today;
		// 本地文件 路径+文件名
		String locationFile = "a.txt";
		// 下载文件
		ChannelSftp sftpConnection = sftpConnection("usmfttst.lenovo.com", 22, "Ex_Hichain_QAS", "Ex_Hichain_QAS");

//      downSftpFile(sftpConnection, locationFile, remoteDirectory, downloadFile, locationDirectory);

		ByteArrayOutputStream downSftpSO = downSftpSO(sftpConnection, remoteDirectory, downloadFile);
		String string = downSftpSO.toString();
		log.info(string);

		sessionClose();
		sftpClose(sftpConnection);
	}
}
